<template>
  <Dialog :title="dialogTitle" v-model="dialogVisible">
    <el-form
      ref="formRef"
      :model="formData"
      :rules="formRules"
      label-width="100px"
      v-loading="formLoading"
    >
      <el-form-item label="所属软件" prop="baseInfoId">
        <el-select
          ref="baseInfoSelectRef"
          v-model="formData.baseInfoId"
          placeholder="请选择所属软件"
          :disabled="isBaseInfoDisabled"
        >
          <el-option
            v-for="item in baseInfoOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="文件夹" prop="dirId" required>
        <el-tree-select
          v-model="formData.dirId"
          :data="fileDirTree"
          :props="defaultProps"
          check-strictly
          default-expand-all
          placeholder="请选择文件夹(必选)"
        />
      </el-form-item>
      <!-- <el-form-item label="类型" prop="type">
        <el-select v-model="formData.type" placeholder="请选择类型">
          <el-option
            v-for="dict in getStrDictOptions(DICT_TYPE.COMPO_SOFTWARE_FILE_TYPE)"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>
      </el-form-item> -->

      <el-form-item label="文件路径" prop="filePath">
        <UploadFile v-model="formData.filePath" :limit="1" :fileSize="999" />
        <div class="el-upload__tip">只能上传1个文件，提交时会自动为文件名添加扩展名</div>
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
      <el-button @click="dialogVisible = false">取 消</el-button>
    </template>
  </Dialog>
</template>
<script setup lang="ts">
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { AttachmentApi, AttachmentVO } from '@/api/compo/compoAttachment'
import { BaseInfoApi, BaseInfoOptionVO } from '@/api/compo/compoBaseInfo'
import { FileDirApi } from '@/api/compo/compoFileDir'
import { convertToOptions } from '@/utils/compoDict'
import { defaultProps, handleTree } from '@/utils/tree'

// 定义树节点接口
interface TreeNode {
  id: number
  name: string
  children?: TreeNode[]
  [key: string]: any
}

/** 软件附件 表单 */
defineOptions({ name: 'AttachmentForm' })

const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

// 上传文件URL配置
const uploadFileUrl =
  import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/ext/file/upload'

const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中：1）修改时的数据加载；2）提交的按钮禁用
const formType = ref('') // 表单的类型：create - 新增；update - 修改
const baseInfoOptions = ref<any[]>([]) // 所属软件下拉选项
const fileDirTree = ref<TreeNode[]>([]) // 文件目录树形结构
const autoFileName = ref(true) // 是否自动填写文件名
const formData = ref({
  id: undefined,
  baseInfoId: undefined as undefined | number,
  type: undefined,
  fileName: undefined as undefined | string,
  filePath: '',
  dirId: undefined as undefined | number
})
const formRules = reactive({
  baseInfoId: [{ required: true, message: '所属软件不能为空', trigger: 'change' }],
  dirId: [{ required: true, message: '文件夹不能为空', trigger: 'change' }],
  // type: [{ required: true, message: '类型不能为空', trigger: 'change' }],
  fileName: [{ required: true, message: '文件名不能为空', trigger: 'blur' }],
  filePath: [{ required: true, message: '文件路径不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
const baseInfoSelectRef = ref() // 所属软件选择器的引用
const isBaseInfoDisabled = ref(false) // 控制软件选择框是否禁用

/** 获取所属软件下拉列表 */
const getBaseInfoOptions = async () => {
  try {
    const data = await BaseInfoApi.listAllNormal()
    baseInfoOptions.value = convertToOptions(data)
  } catch (error) {
    console.error('获取所属软件列表失败:', error)
  }
}

/** 获取文件目录树 */
const getFileDirTree = async () => {
  try {
    fileDirTree.value = []
    const data = await FileDirApi.getFileDirList({})
    const root: TreeNode = { id: 0, name: '顶级文件目录', children: [] }
    root.children = handleTree(data, 'id', 'preId') as unknown as TreeNode[]
    fileDirTree.value = [root]
  } catch (error) {
    console.error('获取文件目录树失败:', error)
  }
}

/** 处理文件路径变化，自动提取文件名 */
const handleFileChange = (newFilePath: string) => {
  if (!newFilePath || !autoFileName.value) return

  // 获取文件路径中的文件名
  let fileNameFromPath = ''

  // 根据文件路径获取原始文件名
  if (newFilePath.includes('/')) {
    fileNameFromPath = newFilePath.substring(newFilePath.lastIndexOf('/') + 1)
  } else {
    fileNameFromPath = newFilePath
  }

  // 如果从路径中获取不到文件名，则返回
  if (!fileNameFromPath) return

  // 如果文件名包含扩展名，去掉扩展名
  if (fileNameFromPath.includes('.')) {
    formData.value.fileName = fileNameFromPath.substring(0, fileNameFromPath.lastIndexOf('.'))
  } else {
    formData.value.fileName = fileNameFromPath
  }
}

/** 打开弹窗 */
const open = async (type: string, id?: number, presetBaseInfoId?: number, presetDirId?: number) => {
  dialogVisible.value = true
  dialogTitle.value = t('action.' + type)
  formType.value = type
  resetForm()

  // 获取所属软件下拉列表和文件目录树
  await Promise.all([getBaseInfoOptions(), getFileDirTree()])

  // 如果传入了预设的软件ID，则设置并禁用软件选择
  if (presetBaseInfoId) {
    formData.value.baseInfoId = presetBaseInfoId
    isBaseInfoDisabled.value = true
  } else {
    isBaseInfoDisabled.value = false
  }

  // 如果传入了预设的文件夹ID，则设置文件夹
  if (presetDirId) {
    formData.value.dirId = presetDirId
  }

  // 修改时，设置数据
  if (id) {
    formLoading.value = true
    try {
      formData.value = await AttachmentApi.getAttachment(id)
      // 编辑时也禁用软件选择
      isBaseInfoDisabled.value = true
      // 编辑时默认不自动更新文件名，避免覆盖已有名称
      autoFileName.value = false
    } finally {
      formLoading.value = false
    }
  } else {
    // 新增时默认启用自动文件名
    autoFileName.value = true
  }
}
defineExpose({ open, formData, baseInfoSelectRef }) // 提供方法和引用，用于父组件访问

/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件，用于操作成功后的回调
const submitForm = async () => {
  // 校验表单
  await formRef.value.validate()

  // 检查并添加文件扩展名
  ensureFileNameExtension()

  // 提交请求
  formLoading.value = true
  try {
    // 获取文件路径中的文件名
    const filePath = formData.value.filePath

    // 根据文件路径获取原始文件名
    if (filePath.includes('/')) {
      formData.value.fileName = filePath.substring(filePath.lastIndexOf('/') + 1)
    } else {
      formData.value.fileName = filePath
    }

    const data = formData.value as unknown as AttachmentVO
    if (formType.value === 'create') {
      await AttachmentApi.createAttachment(data)
      message.success(t('common.createSuccess'))
    } else {
      await AttachmentApi.updateAttachment(data)
      message.success(t('common.updateSuccess'))
    }
    dialogVisible.value = false
    // 发送操作成功的事件
    emit('success')
  } finally {
    formLoading.value = false
  }
}

/** 确保文件名有正确的扩展名 */
const ensureFileNameExtension = () => {
  if (!formData.value.fileName || !formData.value.filePath) return

  // 获取文件路径中的文件名
  const filePath = formData.value.filePath
  let fileNameFromPath = ''

  // 根据文件路径获取原始文件名
  if (filePath.includes('/')) {
    fileNameFromPath = filePath.substring(filePath.lastIndexOf('/') + 1)
  } else {
    fileNameFromPath = filePath
  }

  // 如果从路径中获取不到文件名，则返回
  if (!fileNameFromPath) return

  // 获取文件扩展名
  const fileExt = fileNameFromPath.includes('.')
    ? fileNameFromPath.substring(fileNameFromPath.lastIndexOf('.'))
    : ''

  // 检查当前文件名是否包含扩展名
  if (fileExt && !formData.value.fileName.endsWith(fileExt)) {
    // 文件名不包含扩展名，添加它
    formData.value.fileName = formData.value.fileName + fileExt
  }
}

/** 重置表单 */
const resetForm = () => {
  formData.value = {
    id: undefined,
    baseInfoId: undefined,
    type: undefined,
    fileName: undefined as undefined | string,
    filePath: '',
    dirId: undefined
  }
  formRef.value?.resetFields()
}
</script>